
#include "evalsoc.h"



#define PCLKFREQ                (50 * 1000000)
#define BAUD_RATE(n)            (PCLKFREQ / (n) / 16)




/* Register offsets */
#define UART_REG_TXFIFO         0x00
#define UART_REG_RXFIFO         0x04
#define UART_REG_TXCTRL         0x08
#define UART_REG_RXCTRL         0x0c
#define UART_REG_IE             0x10
#define UART_REG_IP             0x14
#define UART_REG_DIV            0x18

/* TXCTRL register */
#define UART_TXEN               0x1
#define UART_TXWM(x)            (((x) & 0xffff) << 16)

/* RXCTRL register */
#define UART_RXEN               0x1
#define UART_RXWM(x)            (((x) & 0xffff) << 16)

/* IP register */
#define UART_IP_TXWM            0x1
#define UART_IP_RXWM            0x2

#define UART_TXFIFO_FULL        (1<<31)
#define UART_RXFIFO_EMPTY       (1<<31)

#define UART_TXCTRL_TXCNT_OFS   (16)
#define UART_TXCTRL_TXCNT_MASK  (0x1F << UART_TXCTRL_TXCNT_OFS)
#define UART_TXCTRL_TXEN_OFS    (0)
#define UART_TXCTRL_TXEN_MASK   (0x1 << UART_TXCTRL_TXEN_OFS)
#define UART_TXCTRL_NSTOP_OFS   (1)
#define UART_TXCTRL_NSTOP_MASK  (0x3 << UART_TXCTRL_NSTOP_OFS)

#define UART_RXCTRL_RXCNT_OFS   (16)
#define UART_RXCTRL_RXCNT_MASK  (0x1F << UART_RXCTRL_RXCNT_OFS)
#define UART_RXCTRL_RXEN_OFS    (0)
#define UART_RXCTRL_RXEN_MASK   (0x1 << UART_RXCTRL_RXEN_OFS)

#define UART_IE_TXIE_OFS        (0)
#define UART_IE_TXIE_MASK       (0x1 << UART_IE_TXIE_OFS)
#define UART_IE_RXIE_OFS        (1)
#define UART_IE_RXIE_MASK       (0x1 << UART_IE_RXIE_OFS)

#define UART_IP_TXIP_OFS        (0)
#define UART_IP_TXIP_MASK       (0x1 << UART_IP_TXIP_OFS)
#define UART_IP_RXIP_OFS        (1)
#define UART_IP_RXIP_MASK       (0x1 << UART_IP_RXIP_OFS)






int32_t uart_init( dw_uart_regs_t * puart, uint32_t baudrate)
{
    if (__RARELY(puart == NULL)) {
        return -1;
    }


    /* DLAB = 1  */
    puart->LCR = 0x83;
  
    /* Set DLL for baudrate */
    puart->DLL = BAUD_RATE(115200) & 0xff;
    puart->DLH = (BAUD_RATE(115200) >> 8) & 0xff;

    /* DLAB = 0, LCR: Length 8, no parity, 1 stop bit. */
    puart->LCR = 0x03;

    /* IER to */
    puart->IER = 0x80;
    
    /* FCR: Enable FIFO, reset TX and RX. */
    puart->FCR = 0x97;
    return 0;
}


int32_t uart_write( dw_uart_regs_t * puart, uint8_t val )
{
    if (__RARELY(puart == NULL)) {
        return -1;
    }

    while ( (puart->LSR & 0x20) == 0 ) {
        __NOP();
    }
    
    /**/
    puart->THR = (uint32_t)val;
    return 0;
}


uint8_t uart_read( dw_uart_regs_t * puart )
{

    if (__RARELY(puart == NULL)) {
        return -1;
    }

    /**/
    while ( (puart->LSR & 0x1) == 0 ) {
        __NOP();
    }

    return (uint8_t)( puart->RBR );
}


/*
非阻塞.
返回值 < 0 表示没有字符.
*/
int uart_try_getch( dw_uart_regs_t * puart )
{
    if ( (puart->LSR & 0x1) == 0 ) {
        return -1;
    } else {
        return (uint8_t)( puart->RBR );
    }
}




